package cn.stronglink.esm27.collection.iot.devices.esm27.message;

import java.util.ArrayList;
import java.util.List;

import cn.stronglink.esm27.collection.iot.devices.esm27.entity.AlarmInfoEntity;
import cn.stronglink.esm27.collection.iot.devices.esm27.entity.SensorUseEntity;

/**
 * 消息工具
 * @author yuzhantao
 *
 */
public class ESM27MessageTools {
	/**
	 * 获取传感器使能列表
	 * @param data
	 * @return
	 */
	public static List<SensorUseEntity> getSensorUseList(short data){
		List<SensorUseEntity> ret = new ArrayList<SensorUseEntity>();
		for(int i=0;i<12;i++) {
			SensorUseEntity sensorUse = new SensorUseEntity();
			sensorUse.setChannelNumber((byte)(i+1));
			sensorUse.setUse(isIntNumberNBitONEInBinary(data,i));
			switch(i) {
				case 7:
					sensorUse.setName("无线");
					break;
				case 8:
					sensorUse.setName("北斗");
					break;
				case 9:
					sensorUse.setName("声光报警");
					break;
				case 10:
					sensorUse.setName("泵");
					break;
				case 11:
					sensorUse.setName("离线报警");
					break;
				default:
					sensorUse.setName("传感器");
					break;
			}
			ret.add(sensorUse);
		}
		
		return ret;
	}
	
	/**
	 * 根据协议中的数据获取报警信息
	 * @param datas
	 * @param isShowAll 是否显示全部信息（当显示全部信息时，未报警的信息也会显示）
	 * @return
	 */
	public static List<AlarmInfoEntity> getAlarmInfoList(int datas,boolean isShowAll){
		List<AlarmInfoEntity> ret = new ArrayList<AlarmInfoEntity>();
		
		for(int i=0;i<28;i++) {
			boolean isAlarm=isIntNumberNBitONEInBinary(datas,i); 
			if(isAlarm || isShowAll) {
				int sensorNumber = i/4+1;
				AlarmInfoEntity alarmInfo = new AlarmInfoEntity();
				alarmInfo.setSensorChannelNumber(sensorNumber);
				switch(i%4) {
				case 0:
					alarmInfo.setAlarmContent("AL报警");
					break;
				case 1:
					alarmInfo.setAlarmContent("AH报警");
					break;
				case 2:
					alarmInfo.setAlarmContent("STEL报警");
					break;
				case 3:
					alarmInfo.setAlarmContent("TWA报警");
					break;
				}
				alarmInfo.setSensorName("传感器"+sensorNumber);
				alarmInfo.setAlarm(isAlarm);
				ret.add(alarmInfo);
			}
		}
		
		boolean isAlarm = !isIntNumberNBitONEInBinary(datas,28);
		if(isAlarm || isShowAll) {
			AlarmInfoEntity alarmInfo = new AlarmInfoEntity();
			alarmInfo.setSensorName("电池");
			alarmInfo.setAlarmContent("欠压报警");
			alarmInfo.setAlarm(isAlarm);
			ret.add(alarmInfo);
		}
		isAlarm = !isIntNumberNBitONEInBinary(datas,29);
		if(isAlarm || isShowAll) {
			AlarmInfoEntity alarmInfo = new AlarmInfoEntity();
			alarmInfo.setSensorName("泵");
			alarmInfo.setAlarmContent("堵报警");
			alarmInfo.setAlarm(true);
			ret.add(alarmInfo);
		}
		isAlarm = !isIntNumberNBitONEInBinary(datas,30);
		if(isAlarm || isShowAll) {
			AlarmInfoEntity alarmInfo = new AlarmInfoEntity();
			alarmInfo.setSensorName("北斗");
			alarmInfo.setAlarmContent("信号异常报警");
			alarmInfo.setAlarm(true);
			ret.add(alarmInfo);
		}
		isAlarm = !isIntNumberNBitONEInBinary(datas,31);
		if(isAlarm || isShowAll) {
			AlarmInfoEntity alarmInfo = new AlarmInfoEntity();
			alarmInfo.setSensorName("无线");
			alarmInfo.setAlarmContent("接入异常报警");
			alarmInfo.setAlarm(true);
			ret.add(alarmInfo);
		}
		return ret;
	}
	/**
	 * 判断指定int数值的某位是否为1
	 * @param number
	 * @param nbit
	 * @return
	 */
	private static boolean isIntNumberNBitONEInBinary(int number,int nbit){  
		StringBuffer sb = new StringBuffer();
		sb.append(Integer.toBinaryString(number));
		while(sb.length()<32) {
			sb.insert(0, "0");
		}
		return sb.toString().substring(nbit, nbit+1).equals("1");
	}  
	
	private static boolean isIntNumberNBitONEInBinary(short number,int nbit){     
		StringBuffer sb = new StringBuffer();
		sb.append(Integer.toBinaryString(number));
		while(sb.length()<12) {
			sb.insert(0, "0");
		}
		return sb.toString().substring(nbit, nbit+1).equals("1");
	} 
	
	/**
	 * 计算校验码
	 * @param srcDatas
	 * @return
	 */
	public static short calcCRC(byte[] srcDatas) {
	    return calcCRC(srcDatas,0,srcDatas.length);
	}
	
	/**
	 * 计算校验码
	 * @param srcDatas
	 * @param offset
	 * @param length
	 * @return
	 */
	public static short calcCRC(byte[] srcDatas,int offset,int length) {
		int len = length;  
	    //预置 1 个 16 位的寄存器为十六进制FFFF, 称此寄存器为 CRC寄存器。  
	    int crc = 0xFFFF;  
	    int i, j;   
	    for (i = offset; i < len; i++) {  
	        //把第一个 8 位二进制数据 与 16 位的 CRC寄存器的低 8 位相异或, 把结果放于 CRC寄存器  
	        crc = ((crc & 0xFF00) | (crc & 0x00FF) ^ (srcDatas[i] & 0xFF));  
	        for (j = 0; j < 8; j++) {  
	            //把 CRC 寄存器的内容右移一位( 朝低位)用 0 填补最高位, 并检查右移后的移出位  
	            if ((crc & 0x0001) > 0) {  
	                //如果移出位为 1, CRC寄存器与多项式A001进行异或  
	                crc = crc >> 1;  
	                crc = crc ^ 0xA001;  
	            } else  
	                //如果移出位为 0,再次右移一位  
	                crc = crc >> 1;  
	        }  
	    }  
	    
	    return Short.reverseBytes((short)crc);
//	    byte[] bCrc = ByteUtil.shortToByteArr((short)crc);
//	    byte temp = bCrc[0];
//	    bCrc[0]=bCrc[1];
//	    bCrc[1]=temp;
//	    return bCrc;
	}
}
